package com.java.com.atlassian.jira_soapclient;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.opensaml.Configuration;
import org.opensaml.DefaultBootstrap;
import org.opensaml.saml2.core.Response;
import org.opensaml.xml.ConfigurationException;
import org.opensaml.xml.io.Unmarshaller;
import org.opensaml.xml.io.UnmarshallerFactory;
import org.opensaml.xml.io.UnmarshallingException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;

/**
 * @author suresh@wso2.com
 *         This class is exposed as an axis2 service. *
 *         Oreginal code is based on the JIRA SOAP client distrinution,
 *         https://svn.atlassian.com/svn/public/atlassian/rpc
 *         -jira-plugin/tags/atlassian_jira_4_1_1_1/jira-soapclient/ *
 */

public class JIRAService {

    // Session data
    private static boolean bootStrapped = false;
    //private static final Log log = LogFactory.getLog(JIRAService.class);

//    public static void main(String args[]){
//        new JIRAService().testRun();
//    }

    public RemoteProject[] getUserProjects(String username, String password, String baseUrl) throws MalformedURLException, RemoteException {
    	Timing timing = Timing.startTiming("getting user projects...");
    	SOAPSession session = this.logIn(username, password, baseUrl);        
        RemoteProject[] remoteProject = session.getJiraSoapService().getProjectsNoSchemes(session.getAuthenticationToken());
        session.getJiraSoapService().logout(session.getAuthenticationToken());
        timing.printTiming();
        return remoteProject;
    }
    
    public  RemoteIssue[] getUserIssues(String username, String password, String baseUrl,int numIssues) throws MalformedURLException, RemoteException {
    	Timing timing = Timing.startTiming("getting user issues...");
    	SOAPSession soapSession = this.logIn(username, password, baseUrl);        
        String[] projectKey = this.getUserProjectKeys(soapSession); 
        RemoteIssue[] issues = soapSession.getJiraSoapService().getIssuesFromTextSearchWithProject(soapSession.getAuthenticationToken(),projectKey,null,numIssues);
        soapSession.getJiraSoapService().logout(soapSession.getAuthenticationToken());
        timing.printTiming();        
        return issues;
    }



    // -------------------------------------------- Private methods ----------------------------------------------------------

    private SOAPSession logIn(String userName, String passWord, String baseUrl) throws MalformedURLException, RemoteException {

        SOAPSession soapSession = null;
        Timing timing = Timing.startTiming("JIRA SOAP client running");
        try {
            soapSession = new SOAPSession(new URL(baseUrl));
            Timing loginTiming = Timing.startTiming("Working on Log-in");
            soapSession.connect(userName, passWord);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            throw e;
        } catch (RemoteException e) {
            e.printStackTrace();
            throw e;
        } finally {
            timing.printTiming();
        }
        return soapSession;
    }

    private SOAPSession samlLogIn(String saml2Token, String baseUrl) throws ParserConfigurationException, SAXException, IOException, UnmarshallingException, ConfigurationException {

        Timing timing = Timing.startTiming("JIRA SOAP client running");
        SOAPSession soapSession = null;
        try {
            soapSession = new SOAPSession(new URL(baseUrl));
            Response response = this.unmarshall(saml2Token);
            String subject = response.getAssertions().get(0).getSubject()
                    .getNameID().getValue();
            soapSession.connect(subject, saml2Token);

        } catch (ParserConfigurationException e) {
            e.printStackTrace();
            throw e;
        } catch (SAXException e) {
            e.printStackTrace();
            throw e;
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } catch (UnmarshallingException e) {
            e.printStackTrace();
            throw e;
        } catch (ConfigurationException e) {
            e.printStackTrace();
            throw e;
        } finally {
            timing.printTiming();
        }

        return soapSession;
    }

    private String[] getUserProjectKeys(SOAPSession soapSession) throws RemotePermissionException, RemoteAuthenticationException, com.atlassian.jira.rpc.soap.client.RemoteException, RemoteException{
    	
    	RemoteProject[] project = soapSession.getJiraSoapService().getProjectsNoSchemes(soapSession.getAuthenticationToken());
    	int numOfProjects = project.length;
    	String[] projectKey = new String[numOfProjects];
    	for(int i=0; i<numOfProjects; i++){
    		projectKey[i] = project[i].getKey();
    	}
    	return projectKey;
    }
    
    private void testRun() {

        String baseUrl = "http://localhost:8080/rpc/soap/jirasoapservice-v2";
        String userName = "clienta";
        String password = "clienta";
        try {
            SOAPSession session = this.logIn(userName, password, baseUrl);
            Timing timing = Timing.startTiming("getting user projects...");
            String token = session.getAuthenticationToken();
            String[] projects = new String[1];
            projects[0] = "CLIENTAPROJA";
            String search= null ;

            RemoteIssue[] issues = session.getJiraSoapService().getIssuesFromTextSearchWithProject(token,projects,search,10);
            //RemoteFilter[] filter = session.getJiraSoapService().getFavouriteFilters(token); 
            
            System.out.println(issues.toString()+"/n"+timing.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Response unmarshall(String authReqStr)
            throws ParserConfigurationException, SAXException, IOException,
            UnmarshallingException, ConfigurationException {

        doBootstrap();
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
                .newInstance();
        documentBuilderFactory.setNamespaceAware(true);
        DocumentBuilder docBuilder = documentBuilderFactory
                .newDocumentBuilder();
        Document document = docBuilder.parse(new ByteArrayInputStream(
                authReqStr.trim().getBytes()));
        Element element = document.getDocumentElement();
        UnmarshallerFactory unmarshallerFactory = Configuration
                .getUnmarshallerFactory();
        Unmarshaller unmarshaller = unmarshallerFactory
                .getUnmarshaller(element);
        return (Response) unmarshaller.unmarshall(element);
    }

    private void doBootstrap() throws ConfigurationException {
        if (!bootStrapped) {
            DefaultBootstrap.bootstrap();
            bootStrapped = true;
        }
    }
}
